// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置（北京时间UTC+8）
// const long gmtOffset_sec = 8 * 3600;
// const int daylightOffset_sec = 0;

// // 显示布局参数
// #define LINE_HEIGHT 24
// #define TEXT_SIZE 2
// #define COLUMN_START 5

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
// } displayData;

// void setup() {
//   Serial.begin(115200);
  
//   // 屏幕初始化
//   tft.init();
//   tft.setRotation(1); 
//   tft.fillScreen(TFT_BLACK);
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextSize(TEXT_SIZE);

//   // 连接WiFi
//   WiFi.begin(ssid, password);
//   while (WiFi.status() != WL_CONNECTED) {
//     delay(500);
//     tft.drawString("Connecting WiFi...", COLUMN_START, 0);
//   }
  
//   // 配置NTP
//   configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org", "time.nist.gov");
  
//   // MQTT连接
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback(callback);
//   mqttReconnect();
// }

// void callback(char* topic, byte* payload, unsigned int length) {
//   StaticJsonDocument<200> doc;
//   deserializeJson(doc, payload, length);
  
//   displayData.temperature = doc["temperature"] | NAN;
//   displayData.humidity = doc["humidity"] | NAN;
// }

// void mqttReconnect() {
//   while (!client.connected()) {
//     if (client.connect("ESP32Client")) {
//       client.subscribe(mqttTopic);
//     }
//     delay(5000);
//   }
// }

// void updateDateTime() {
//   struct tm timeinfo;
//   if (getLocalTime(&timeinfo)) {
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
//   }
// }

// void drawDisplay() {
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.drawString("Temperature:", COLUMN_START, 0 * LINE_HEIGHT);
//   tft.setCursor(10,10,1);
//   tft.drawString(displayData.temperature != NAN ? 
//                 String(displayData.temperature, 1) + " C" : "--.- C", 
//                 COLUMN_START, 1 * LINE_HEIGHT);

//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.drawString("Humidity:", COLUMN_START, 2 * LINE_HEIGHT);
//   tft.drawString(displayData.humidity != NAN ? 
//                 String(displayData.humidity, 1) + " %" : "--.- %", 
//                 COLUMN_START, 3 * LINE_HEIGHT);

//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.drawString(displayData.timeStr, COLUMN_START, 4 * LINE_HEIGHT);
  
//   tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
//   tft.drawString(displayData.dateStr, COLUMN_START, 5 * LINE_HEIGHT);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastUpdate = 0;
//   if (millis() - lastUpdate >= 1000) {
//     updateDateTime();
//     tft.fillScreen(TFT_BLACK); // 全屏刷新
//     drawDisplay();
//     lastUpdate = millis();
//   }
// }























//########################################################################################################













//正常显示的代码##############################################################################################################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置（北京时间UTC+8）
// const long gmtOffset_sec = 8 * 3600;
// const int daylightOffset_sec = 0;

// // 显示布局参数
// #define TEXT_SIZE 1  // 字体大小
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define CENTER_X (SCREEN_WIDTH / 2)  // 屏幕中心X坐标
// #define CENTER_Y (SCREEN_HEIGHT / 2)  // 屏幕中心Y坐标
// #define LINE_HEIGHT (TEXT_SIZE * 16)  // 每行高度
// #define COLUMN_START 5  // 列起始位置

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
// } displayData;

// void setup() {
//   Serial.begin(115200);
  
//   // 屏幕初始化
//   tft.init();
//   tft.setRotation(1); 
//   tft.fillScreen(TFT_BLACK);
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextSize(TEXT_SIZE);

//   // 连接WiFi
//   WiFi.begin(ssid, password);
//   while (WiFi.status() != WL_CONNECTED) {
//     delay(500);
//     tft.drawString("Connecting WiFi...", COLUMN_START, 0);
//   }
  
//   // 配置NTP
//   configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org", "time.nist.gov");
  
//   // MQTT连接
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback(callback);
//   mqttReconnect();
// }

// void callback(char* topic, byte* payload, unsigned int length) {
//   StaticJsonDocument<200> doc;
//   deserializeJson(doc, payload, length);
  
//   displayData.temperature = doc["temperature"] | NAN;
//   displayData.humidity = doc["humidity"] | NAN;
// }

// void mqttReconnect() {
//   while (!client.connected()) {
//     if (client.connect("ESP32Client")) {
//       client.subscribe(mqttTopic);
//     }
//     delay(1000);
//   }
// }

// void updateDateTime() {
//   struct tm timeinfo;
//   if (getLocalTime(&timeinfo)) {
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
//   }
// }

// void drawDisplay() {
//   // 温度
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.drawString("Temp:", COLUMN_START, CENTER_Y - 2 * LINE_HEIGHT);
//   tft.drawString(displayData.temperature != NAN ? 
//                 String(displayData.temperature, 1) + " C" : "--.- C", 
//                 CENTER_X, CENTER_Y - 2 * LINE_HEIGHT, TEXT_SIZE);

//   // 湿度
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.drawString("Hum:", COLUMN_START, CENTER_Y - LINE_HEIGHT);
//   tft.drawString(displayData.humidity != NAN ? 
//                 String(displayData.humidity, 1) + " %" : "--.- %", 
//                 CENTER_X, CENTER_Y - LINE_HEIGHT, TEXT_SIZE);

//   // 时间
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.drawString("TIME:", COLUMN_START, CENTER_Y);
//   tft.drawString(displayData.timeStr, CENTER_X, CENTER_Y, TEXT_SIZE);
  
//   // 日期
//   tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
//   tft.drawString("DATE:", COLUMN_START, CENTER_Y + LINE_HEIGHT);
//   tft.drawString(displayData.dateStr, CENTER_X, CENTER_Y + LINE_HEIGHT, TEXT_SIZE);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastUpdate = 0;
//   if (millis() - lastUpdate >= 1000) {
//     updateDateTime();
//     tft.fillScreen(TFT_BLACK); // 全屏刷新
//     drawDisplay();
//     lastUpdate = millis();
//   }
// }




//再次完善代码###############################################################################################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include "myFont.h"
// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置（北京时间UTC+8）
// const long gmtOffset_sec = 8 * 3600;
// const int daylightOffset_sec = 0;

// // 显示布局参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define TOP_POS 5          // 顶部起始位置
// #define BOTTOM_POS 110     // 底部起始位置
// #define TIME_FONT_SIZE 4   // 时间字体大小
// #define DATE_FONT_SIZE 2   // 日期字体大小
// #define SENSOR_FONT_SIZE 1 // 传感器字体大小
// #define MAX_WIFI_RETRY 20  // WiFi最大重试次数

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
// } displayData;

// void setup() {
//   Serial.begin(115200);
//   tft.unloadFont();
//   // 屏幕初始化
//   tft.init();
//   tft.setRotation(1); 
//   tft.fillScreen(TFT_BLACK);
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);

//   // 连接WiFi（带超时机制）
//   WiFi.begin(ssid, password);
//   int wifiRetry = 0;
//   while (WiFi.status() != WL_CONNECTED && wifiRetry < MAX_WIFI_RETRY) {
//     delay(500);
//     tft.setTextDatum(TC_DATUM);
//     tft.drawString("WiFi Connecting...", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     wifiRetry++;
//   }
  
//   if(WiFi.status() != WL_CONNECTED) {
//     tft.fillScreen(TFT_BLACK);
//     tft.drawString("WiFi Failed!", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     delay(2000);
//     ESP.restart();
//   }

//   // 配置NTP
//   configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org", "time.nist.gov");
  
//   // MQTT连接
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback(callback);
//   mqttReconnect();
// }

// void callback(char* topic, byte* payload, unsigned int length) {
//   StaticJsonDocument<200> doc;
//   deserializeJson(doc, payload, length);
  
//   displayData.temperature = doc["temperature"] | NAN;
//   displayData.humidity = doc["humidity"] | NAN;
// }

// void mqttReconnect() {
//   while (!client.connected()) {
//     if (client.connect("ESP32Client")) {
//       client.subscribe(mqttTopic);
//     }
//     delay(1000);
//   }
// }

// void updateDateTime() {
//   struct tm timeinfo;
//   if (getLocalTime(&timeinfo)) {
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
//   }
// }

// void drawDisplay() {
//   tft.fillScreen(TFT_BLACK);
  
//   // 绘制温度（左上角）
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.setTextDatum(TL_DATUM);
//   tft.setTextSize(SENSOR_FONT_SIZE);
//   tft.drawString("TEM:", 5, TOP_POS);
//   tft.drawString(displayData.temperature != NAN ? 
//                 String(displayData.temperature, 1) + " C" : "--.- C", 
//                 5, TOP_POS + 16);

//   // 绘制湿度（右上角）
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.setTextDatum(TR_DATUM);
//   tft.drawString("HUM:", SCREEN_WIDTH-5, TOP_POS);
//   tft.drawString(displayData.humidity != NAN ? 
//                 String(displayData.humidity, 1) + " %" : "--.- %", 
//                 SCREEN_WIDTH-5, TOP_POS + 16);

//   // 绘制时间（居中）
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextDatum(TC_DATUM);
//   tft.setTextSize(TIME_FONT_SIZE);
//   tft.drawString(displayData.timeStr, SCREEN_WIDTH/2, SCREEN_HEIGHT/2 - 20);

//   // 绘制日期（底部居中）
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.setTextDatum(BC_DATUM);
//   tft.setTextSize(DATE_FONT_SIZE);
//   tft.drawString(displayData.dateStr, SCREEN_WIDTH/2, BOTTOM_POS);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastUpdate = 0;
//   if (millis() - lastUpdate >= 1000) {
//     updateDateTime();
//     drawDisplay();
//     lastUpdate = millis();
//   }
// }




//######显示眨眼效果################################################################################################################################

// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include "myFont.h"
// #include "pic.h"
// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置（北京时间UTC+8）
// const long gmtOffset_sec = 8 * 3600;
// const int daylightOffset_sec = 0;

// // 显示布局参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define TOP_POS 5          // 顶部起始位置
// #define BOTTOM_POS 110     // 底部起始位置
// #define TIME_FONT_SIZE 4   // 时间字体大小
// #define DATE_FONT_SIZE 2   // 日期字体大小
// #define SENSOR_FONT_SIZE 1 // 传感器字体大小
// #define MAX_WIFI_RETRY 20  // WiFi最大重试次数

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
// } displayData;

// void setup() {
//   Serial.begin(115200);
//   tft.unloadFont();
//   // 屏幕初始化
//   tft.init();
//   tft.setRotation(1); 
//   tft.fillScreen(TFT_WHITE);
//   // tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setSwapBytes(true);
//   tft.pushImage(0,0,128,128,p9);
//   // 连接WiFi（带超时机制）
//   WiFi.begin(ssid, password);
//   int wifiRetry = 0;
//   while (WiFi.status() != WL_CONNECTED && wifiRetry < MAX_WIFI_RETRY) {
//     delay(500);
//     tft.setTextDatum(TC_DATUM);
//     tft.drawString("WiFi Connecting...", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     wifiRetry++;
//   }
  
//   if(WiFi.status() != WL_CONNECTED) {
//     tft.fillScreen(TFT_BLACK);
//     tft.drawString("WiFi Failed!", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     delay(2000);
//     ESP.restart();
//   }

//   // 配置NTP
//   configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org", "time.nist.gov");

//   // 等待NTP同步完成
//   struct tm timeinfo;
//   while (!getLocalTime(&timeinfo)) {
//     Serial.println("Waiting for time sync...");
//     delay(2000);
//   }
//   // MQTT连接
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback(callback);
//   mqttReconnect();
// }

// void callback(char* topic, byte* payload, unsigned int length) {
//   StaticJsonDocument<200> doc;
//   deserializeJson(doc, payload, length);
  
//   displayData.temperature = doc["temperature"] | NAN;
//   displayData.humidity = doc["humidity"] | NAN;
// }

// void mqttReconnect() {
//   while (!client.connected()) {
//     if (client.connect("ESP32Client")) {
//       client.subscribe(mqttTopic);
//     }
//     delay(1000);
//   }
// }

// void updateDateTime() {
//   time_t now;
//   struct tm timeinfo;
//   time(&now);
//   localtime_r(&now, &timeinfo);  // 使用 localtime_r 获取本地时间
  
//   strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//   strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }

// void drawDisplay() {
//   tft.fillScreen(TFT_BLACK);
  
//   // 绘制温度（左上角）
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.setTextDatum(TL_DATUM);
//   tft.setTextSize(SENSOR_FONT_SIZE);
//   tft.drawString("TEM:", 5, TOP_POS);
//   tft.drawString(displayData.temperature != NAN ? 
//                 String(displayData.temperature, 1) + " C" : "--.- C", 
//                 5, TOP_POS + 16);

//   // 绘制湿度（右上角）
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.setTextDatum(TR_DATUM);
//   tft.drawString("HUM:", SCREEN_WIDTH-5, TOP_POS);
//   tft.drawString(displayData.humidity != NAN ? 
//                 String(displayData.humidity, 1) + " %" : "--.- %", 
//                 SCREEN_WIDTH-5, TOP_POS + 16);

//   // 绘制时间（居中）
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextDatum(TC_DATUM);
//   tft.setTextSize(TIME_FONT_SIZE);
//   tft.drawString(displayData.timeStr, SCREEN_WIDTH/2, SCREEN_HEIGHT/2 + 3);

//   // 绘制日期（底部居中）
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.setTextDatum(BC_DATUM);
//   tft.setTextSize(DATE_FONT_SIZE);
//   tft.drawString(displayData.dateStr, SCREEN_WIDTH/2, BOTTOM_POS + 10);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();
//   // 检测是否连接到Wi-Fi
//   unsigned long wifiCheckStart = millis();
//   while (WiFi.status() != WL_CONNECTED) {
//     delay(1000);
//     if (millis() - wifiCheckStart > 10000) {
//       ESP.restart();
//     }
//   }
//   static unsigned long lastUpdate = 0;
//   if (millis() - lastUpdate >= 1000) {
//     updateDateTime();
//     drawDisplay();
//     lastUpdate = millis();
//   }
// //SCREEN_WIDTH
//   tft.pushImage(0,0,50,50,p1);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p1);
//   delay(50);
//   tft.pushImage(0,0,50,50,p2);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p2);
//   delay(50);
//   tft.pushImage(0,0,50,50,p3);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p3);
//   delay(50);
//   tft.pushImage(0,0,50,50,p4);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p4);
//   delay(50);
//   tft.pushImage(0,0,50,50,p5);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p5);
//   delay(50);
//   tft.pushImage(0,0,50,50,p6);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p6);
//   delay(50);
//   tft.pushImage(0,0,50,50,p7);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p7);
//   delay(50);
//   tft.pushImage(0,0,50,50,p8);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p8);
//   delay(50);
//   tft.pushImage(0,0,50,50,p6);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p6);
//   delay(50);
//   tft.pushImage(0,0,50,50,p4);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p4);
//   delay(50);
//   tft.pushImage(0,0,50,50,p1);
//   tft.pushImage(SCREEN_WIDTH-50,0,50,50,p1);
//   delay(2000);
// }

//####眨眼不自然的代码##############################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include "myFont.h"
// #include "pic.h"

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 50        // 动画帧间隔
// #define EYE_SPACING 80        // 增大眼睛间距
// #define MAX_OFFSET 10         // 最大横向偏移量

// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置
// const long gmtOffset_sec = 8 * 3600;

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
//   int8_t eyeOffset = 0;
//   int8_t moveDir = 1;
// } displayData;

// // 动画帧序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};

// void setup() {
//   Serial.begin(115200);
//   tft.init();
//   tft.setRotation(1);
//   tft.fillScreen(TFT_BLACK);
//   tft.setSwapBytes(true);

//   WiFi.begin(ssid, password);
//   while (WiFi.status() != WL_CONNECTED) delay(500);

//   configTime(gmtOffset_sec, 0, "pool.ntp.org");
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback([](char* topic, byte* payload, unsigned int length) {
//     StaticJsonDocument<200> doc;
//     deserializeJson(doc, payload, length);
//     displayData.temperature = doc["temperature"] | NAN;
//     displayData.humidity = doc["humidity"] | NAN;
//   });
//   mqttReconnect();
// }

// void mqttReconnect() {
//   while (!client.connect("ESP32Client")) delay(1000);
//   client.subscribe(mqttTopic);
// }

// void updateDateTime() {
//   time_t now;
//   struct tm timeinfo;
//   time(&now);
//   localtime_r(&now, &timeinfo);
//   strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//   strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }

// void drawDataArea() {
//   // 温度显示（左下角）
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.setTextDatum(BL_DATUM);
//   tft.drawString("TEM:" + String(displayData.temperature,1) + "C", 5, SCREEN_HEIGHT-5);

//   // 湿度显示（右下角）
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.setTextDatum(BR_DATUM);
//   tft.drawString("HUM:" + String(displayData.humidity,1) + "%", SCREEN_WIDTH-5, SCREEN_HEIGHT-5);

//   // 时间显示（大号字体）
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextDatum(TC_DATUM);
//   tft.setTextSize(3); // 字体放大到3号
//   tft.drawString(displayData.timeStr, SCREEN_WIDTH/2, DATA_TOP + 5);

//   // 日期显示
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.setTextSize(1); // 恢复默认字号
//   tft.drawString(displayData.dateStr, SCREEN_WIDTH/2, DATA_TOP + 35);
// }

// void drawAnimation() {
//   static uint8_t frameCounter = 0;
//   static unsigned long lastMove = 0;
  
//   // 清空动画区域
//   tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);

//   // 计算眼睛位置偏移
//   if(millis() - lastMove > 30) {
//     displayData.eyeOffset += displayData.moveDir;
//     if(abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//     lastMove = millis();
//   }

//   // 计算眨眼帧（1秒完成4帧循环）
//   uint8_t animIndex = (frameCounter / (1000/(4*FRAME_DELAY))) % 4;

//   // 绘制动态眼睛
//   int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
//   int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;
  
//   tft.pushImage(leftX - ANIMATION_WIDTH/2, 
//                ANIM_TOP + 10,
//                ANIMATION_WIDTH, ANIMATION_WIDTH,
//                animFrames[animIndex]);

//   tft.pushImage(rightX - ANIMATION_WIDTH/2,
//                ANIM_TOP + 10,
//                ANIMATION_WIDTH, ANIMATION_WIDTH,
//                animFrames[animIndex]);

//   frameCounter++;
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastDataUpdate = 0;
//   if (millis() - lastDataUpdate >= 1000) {
//     updateDateTime();
//     drawDataArea();
//     lastDataUpdate = millis();
//   }

//   // 保持50ms动画刷新
//   static unsigned long lastAnimUpdate = 0;
//   if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//     drawAnimation();
//     lastAnimUpdate = millis();
//   }
// }



//#####完善眨眼效果的代码################################################################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include "myFont.h"
// #include "pic.h"
// //请在心知天气注册账号，并把"密钥"和"城市"补充完整
// extern const char* host = "api.seniverse.com";
// extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     //输入你的密钥
// extern char* City = "XingTai";  
// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 33        // 加快帧率至30FPS
// #define EYE_SPACING 80        
// #define MAX_OFFSET 10         
// #define BLINK_CYCLE 400       // 眨眼周期缩短至400ms

// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置
// const long gmtOffset_sec = 8 * 3600;

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
//   int8_t eyeOffset = 0;
//   int8_t moveDir = 1;
// } displayData;

// // 动画帧序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};

// void setup() {
//   Serial.begin(115200);
//   tft.init();
//   tft.setRotation(1);
//   tft.fillScreen(TFT_BLACK);
//   tft.setSwapBytes(true);

//   WiFi.begin(ssid, password);
//   while (WiFi.status() != WL_CONNECTED) delay(500);

//   configTime(gmtOffset_sec, 0, "pool.ntp.org");
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback([](char* topic, byte* payload, unsigned int length) {
//     StaticJsonDocument<200> doc;
//     deserializeJson(doc, payload, length);
//     displayData.temperature = doc["temperature"] | NAN;
//     displayData.humidity = doc["humidity"] | NAN;
//   });
//   mqttReconnect();
// }

// void mqttReconnect() {
//   while (!client.connect("ESP32Client")) delay(1000);
//   client.subscribe(mqttTopic);
// }

// void updateDateTime() {
//   time_t now;
//   struct tm timeinfo;
//   time(&now);
//   localtime_r(&now, &timeinfo);
//   strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//   strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }

// void drawDataArea() {
//   // 温度显示（左下角）
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.setTextDatum(BL_DATUM);
//   tft.drawString("TEM:" + String(displayData.temperature,1) + "C", 5, SCREEN_HEIGHT-5);

//   // 湿度显示（右下角）
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.setTextDatum(BR_DATUM);
//   tft.drawString("HUM:" + String(displayData.humidity,1) + "%", SCREEN_WIDTH-5, SCREEN_HEIGHT-5);

//   // 时间显示
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextDatum(TC_DATUM);
//   tft.setTextSize(3);
//   tft.drawString(displayData.timeStr, SCREEN_WIDTH/2, DATA_TOP + 5);

//   // 日期显示
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.setTextSize(1);
//   tft.drawString(displayData.dateStr, SCREEN_WIDTH/2, DATA_TOP + 35);
// }

// void drawAnimation() {
//   static unsigned long lastBlink = 0;
//   static uint8_t animPhase = 0;
  
//   // 清空动画区域
//   tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);

//   // 眼睛移动控制（20ms更新）
//   if(millis() - lastBlink > 20) {
//     displayData.eyeOffset += displayData.moveDir;
//     if(abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//     lastBlink = millis();
//   }

//   // 加速眨眼状态机
//   static unsigned long blinkTimer = 0;
//   static uint8_t blinkState = 0;
//   if(millis() - blinkTimer > BLINK_CYCLE/4) { // 每100ms切换一帧
//     blinkState = (blinkState + 1) % 4;
//     blinkTimer = millis();
//   }

//   // 计算眼睛位置
//   int leftX = (SCREEN_WIDTH - EYE_SPACING)/2 + displayData.eyeOffset;
//   int rightX = (SCREEN_WIDTH + EYE_SPACING)/2 + displayData.eyeOffset;

//   // 绘制动态眼睛
//   tft.pushImage(leftX - ANIMATION_WIDTH/2, 
//                ANIM_TOP + 10,
//                ANIMATION_WIDTH, ANIMATION_WIDTH,
//                animFrames[blinkState]);

//   tft.pushImage(rightX - ANIMATION_WIDTH/2,
//                ANIM_TOP + 10,
//                ANIMATION_WIDTH, ANIMATION_WIDTH,
//                animFrames[blinkState]);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastDataUpdate = 0;
//   if (millis() - lastDataUpdate >= 1000) {
//     updateDateTime();
//     drawDataArea();
//     lastDataUpdate = millis();
//   }

//   // 保持30FPS动画刷新
//   static unsigned long lastAnimUpdate = 0;
//   if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//     drawAnimation();
//     lastAnimUpdate = millis();
//   }
// }



//ESP8266####################################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <NTPClient.h>
// #include <WiFiUdp.h>
// #include <ArduinoJson.h>
// #include "myFont.h"

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // NTP客户端配置
// WiFiUDP ntpUDP;
// NTPClient timeClient(ntpUDP, "pool.ntp.org", 8 * 3600, 60000);

// // 显示布局参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define TOP_POS 5          // 顶部起始位置
// #define BOTTOM_POS 110     // 底部起始位置
// #define TIME_FONT_SIZE 4   // 时间字体大小
// #define DATE_FONT_SIZE 2   // 日期字体大小
// #define SENSOR_FONT_SIZE 1 // 传感器字体大小
// #define MAX_WIFI_RETRY 20  // WiFi最大重试次数

// struct {
//   float temperature = NAN;
//   float humidity = NAN;
//   char timeStr[10] = "--:--";
//   char dateStr[12] = "----/--/--";
// } displayData;

// void setup() {
//   Serial.begin(115200);
//   tft.unloadFont();
//   // 屏幕初始化
//   tft.init();
//   tft.setRotation(1); 
//   tft.fillScreen(TFT_BLACK);
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);

//   // 连接WiFi（带超时机制）
//   WiFi.begin(ssid, password);
//   int wifiRetry = 0;
//   while (WiFi.status() != WL_CONNECTED && wifiRetry < MAX_WIFI_RETRY) {
//     delay(500);
//     tft.setTextDatum(TC_DATUM);
//     tft.drawString("WiFi Connecting...", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     wifiRetry++;
//   }
  
//   if(WiFi.status() != WL_CONNECTED) {
//     tft.fillScreen(TFT_BLACK);
//     tft.drawString("WiFi Failed!", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//     delay(2000);
//     ESP.restart();
//   }

//   // 初始化NTP客户端
//   timeClient.begin();

//   // MQTT连接
//   client.setServer(mqttServer, mqttPort);
//   client.setCallback(callback);
//   mqttReconnect();
// }

// void callback(char* topic, byte* payload, unsigned int length) {
//   StaticJsonDocument<200> doc;
//   deserializeJson(doc, payload, length);
  
//   displayData.temperature = doc["temperature"] | NAN;
//   displayData.humidity = doc["humidity"] | NAN;
// }

// void mqttReconnect() {
//   while (!client.connected()) {
//     if (client.connect("ESP32Client")) {
//       client.subscribe(mqttTopic);
//     }
//     delay(1000);
//   }
// }

// void updateDateTime() {
//   timeClient.update();
//   unsigned long epochTime = timeClient.getEpochTime();
//   struct tm *ptm = gmtime ((time_t *)&epochTime);

//   strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", ptm);
//   strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", ptm);
// }

// void drawDisplay() {
//   tft.fillScreen(TFT_BLACK);
  
//   // 绘制温度（左上角）
//   tft.setTextColor(TFT_CYAN, TFT_BLACK);
//   tft.setTextDatum(TL_DATUM);
//   tft.setTextSize(SENSOR_FONT_SIZE);
//   tft.drawString("TEM:", 5, TOP_POS);
//   tft.drawString(displayData.temperature != NAN ? 
//                 String(displayData.temperature, 1) + " C" : "--.- C", 
//                 5, TOP_POS + 16);

//   // 绘制湿度（右上角）
//   tft.setTextColor(TFT_GREEN, TFT_BLACK);
//   tft.setTextDatum(TR_DATUM);
//   tft.drawString("HUM:", SCREEN_WIDTH-5, TOP_POS);
//   tft.drawString(displayData.humidity != NAN ? 
//                 String(displayData.humidity, 1) + " %" : "--.- %", 
//                 SCREEN_WIDTH-5, TOP_POS + 16);

//   // 绘制时间（居中）
//   tft.setTextColor(TFT_WHITE, TFT_BLACK);
//   tft.setTextDatum(TC_DATUM);
//   tft.setTextSize(TIME_FONT_SIZE);
//   tft.drawString(displayData.timeStr, SCREEN_WIDTH/2, SCREEN_HEIGHT/2 - 20);

//   // 绘制日期（底部居中）
//   tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//   tft.setTextDatum(BC_DATUM);
//   tft.setTextSize(DATE_FONT_SIZE);
//   tft.drawString(displayData.dateStr, SCREEN_WIDTH/2, BOTTOM_POS);
// }

// void loop() {
//   if (!client.connected()) mqttReconnect();
//   client.loop();

//   static unsigned long lastUpdate = 0;
//   if (millis() - lastUpdate >= 1000) {
//     updateDateTime();
//     drawDisplay();
//     lastUpdate = millis();
//   }
// }













//###########ze|zengjia增加天气显示功能#############################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include <HTTPClient.h>
// #include "pic.h"

// // 心知天气配置
// extern const char* host = "api.seniverse.com";
// extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     // 输入你的密钥
// extern char* City = "XingTai";  

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 33        // 加快帧率至30FPS
// #define EYE_SPACING 80
// #define MAX_OFFSET 10
// #define BLINK_CYCLE 400       // 眨眼周期缩短至400ms

// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT

// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();

// // 时区配置
// const long gmtOffset_sec = 8 * 3600;

// struct {
//     float temperature = NAN;
//     float humidity = NAN;
//     char timeStr[10] = "--:--";
//     char dateStr[12] = "----/--/--";
//     char tomorrowWeather[20] = "N/A";
//     int8_t eyeOffset = 0;
//     int8_t moveDir = 1;
//     unsigned long lastWeatherUpdate = 0;
//     unsigned long lastWiFiCheck = 0;
//     int wifiConnectAttempts = 0;
// } displayData;

// // 动画帧序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};

// void setup() {
//     Serial.begin(115200);
//     tft.init();
//     tft.setRotation(1);
//     tft.fillScreen(TFT_BLACK);
//     tft.setSwapBytes(true);

//     WiFi.begin(ssid, password);
//     while (WiFi.status()!= WL_CONNECTED) {
//         delay(1000);
//         Serial.print(".");
//         displayData.wifiConnectAttempts++;
//         if (displayData.wifiConnectAttempts > 30) {
//             Serial.println("Failed to connect to WiFi. Restarting...");
//             ESP.restart();
//         }
//     }
//     Serial.println("");
//     Serial.println("WiFi connected");
//     Serial.println("IP address: ");
//     Serial.println(WiFi.localIP());

//     configTime(gmtOffset_sec, 0, "pool.ntp.org");
//     client.setServer(mqttServer, mqttPort);
//     client.setCallback([](char* topic, byte* payload, unsigned int length) {
//         StaticJsonDocument<200> doc;
//         deserializeJson(doc, payload, length);
//         displayData.temperature = doc["temperature"] | NAN;
//         displayData.humidity = doc["humidity"] | NAN;
//     });
//     mqttReconnect();

//     // 首次获取天气数据
//     fetchWeather();
// }

// void mqttReconnect() {
//     while (!client.connect("ESP32Client")) delay(1000);
//     client.subscribe(mqttTopic);
// }

// void updateDateTime() {
//     time_t now;
//     struct tm timeinfo;
//     time(&now);
//     localtime_r(&now, &timeinfo);
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }

// void drawDataArea() {
//     // 温度显示（左下角）
//     tft.setTextColor(TFT_CYAN, TFT_BLACK);
//     tft.setTextDatum(BL_DATUM);
//     tft.drawString("TEM:" + String(displayData.temperature, 1) + "C", 5, SCREEN_HEIGHT - 5);

//     // 湿度显示（右下角）
//     tft.setTextColor(TFT_GREEN, TFT_BLACK);
//     tft.setTextDatum(BR_DATUM);
//     tft.drawString("HUM:" + String(displayData.humidity, 1) + "%", SCREEN_WIDTH - 5, SCREEN_HEIGHT - 5);

//     // 时间显示
//     tft.setTextColor(TFT_WHITE, TFT_BLACK);
//     tft.setTextDatum(TC_DATUM);
//     tft.setTextSize(3);
//     tft.drawString(displayData.timeStr, SCREEN_WIDTH / 2, DATA_TOP + 5);

//     // 日期显示，向左移动
//     tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//     tft.setTextSize(1);
//     tft.setTextDatum(TL_DATUM);
//     tft.drawString(displayData.dateStr, 5, DATA_TOP + 35);

//     // 明天天气显示
//     tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
//     tft.setTextSize(1);
//     tft.setTextDatum(TR_DATUM);
//     tft.drawString(displayData.tomorrowWeather, SCREEN_WIDTH - 5, DATA_TOP + 35);
// }

// void drawAnimation() {
//     static unsigned long lastBlink = 0;
//     static uint8_t animPhase = 0;

//     // 清空动画区域
//     tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);

//     // 眼睛移动控制（20ms更新）
//     if (millis() - lastBlink > 20) {
//         displayData.eyeOffset += displayData.moveDir;
//         if (abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//         lastBlink = millis();
//     }

//     // 加速眨眼状态机
//     static unsigned long blinkTimer = 0;
//     static uint8_t blinkState = 0;
//     if (millis() - blinkTimer > BLINK_CYCLE / 4) { // 每100ms切换一帧
//         blinkState = (blinkState + 1) % 4;
//         blinkTimer = millis();
//     }

//     // 计算眼睛位置
//     int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
//     int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;

//     // 绘制动态眼睛
//     tft.pushImage(leftX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);

//     tft.pushImage(rightX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);
//     delay(2000);
// }

// // 获取天气数据
// void fetchWeather() {
//     if (WiFi.status()!= WL_CONNECTED) return;

//     HTTPClient http;
//     const int httpPort = 80;
//     if (!espClient.connect(host, httpPort)) {
//         Serial.println("connection failed");
//         return;
//     }

//     String url = "/v3/weather/daily.json?key=" + String(Privat_Key) + "&location=" + String(City) + "&language=en&unit=c&start=0&days=2";
//     espClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
//                     "Host: " + String(host) + "\r\n" +
//                     "Connection: close\r\n\r\n");
//     delay(1000);

//     String answer;
//     while (espClient.available()) {
//         String line = espClient.readStringUntil('\r');
//         answer += line;
//     }
//     espClient.stop();

//     // 提取JSON数据
//     String jsonAnswer;
//     int jsonIndex;
//     for (int i = 0; i < answer.length(); i++) {
//         if (answer[i] == '{') {
//             jsonIndex = i;
//             break;
//         }
//     }
//     jsonAnswer = answer.substring(jsonIndex);

//     Serial.println("Xingtai Weather JSON data:");
//     Serial.println(jsonAnswer);

//     const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
//     DynamicJsonDocument doc(capacity);
//     deserializeJson(doc, jsonAnswer);

//     JsonObject results_0 = doc["results"][0];
//     JsonArray daily = results_0["daily"];
//     if (daily.size() > 1) {
//         JsonObject tomorrow = daily[1];
//         const char* weather = tomorrow["text_day"];
//         if (weather!= nullptr) {
//             strncpy(displayData.tomorrowWeather, weather, sizeof(displayData.tomorrowWeather) - 1);
//             displayData.tomorrowWeather[sizeof(displayData.tomorrowWeather) - 1] = '\0';
//         }
//     }

//     displayData.lastWeatherUpdate = millis();
// }

// void loop() {
//     if (!client.connected()) mqttReconnect();
//     client.loop();

//     // 检查 WiFi 连接
//     if (millis() - displayData.lastWiFiCheck > 5000) {
//         if (WiFi.status()!= WL_CONNECTED) {
//             displayData.wifiConnectAttempts++;
//             if (displayData.wifiConnectAttempts > 30) {
//                 Serial.println("Lost WiFi connection. Restarting...");
//                 ESP.restart();
//             }
//             WiFi.reconnect();
//         } else {
//             displayData.wifiConnectAttempts = 0;
//         }
//         displayData.lastWiFiCheck = millis();
//     }

//     static unsigned long lastDataUpdate = 0;
//     if (millis() - lastDataUpdate >= 1000) {
//         updateDateTime();
//         drawDataArea();
//         lastDataUpdate = millis();
//     }

//     // 每 5 分钟更新一次天气
//     if (millis() - displayData.lastWeatherUpdate >= 5 * 60 * 1000) {
//         fetchWeather();
//         drawDataArea();
//     }

//     // 保持 30FPS 动画刷新
//     static unsigned long lastAnimUpdate = 0;
//     if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//         drawAnimation();
//         lastAnimUpdate = millis();
//     }
// }




//#天气显示完善修改稳定#####################################################
// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include <HTTPClient.h>
// #include "pic.h"
// // 心知天气配置
// extern const char* host = "api.seniverse.com";
// extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     // 输入你的密钥
// extern char* City = "XingTai";  

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* mqttTopic = "sensor";

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 33        // 加快帧率至30FPS
// #define EYE_SPACING 80
// #define MAX_OFFSET 10
// #define BLINK_CYCLE 400       // 眨眼周期缩短至400ms
// #define MAX_WIFI_RETRY 20
// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT
// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();
// // 时区配置
// const long gmtOffset_sec = 8 * 3600;
// struct {
//     float temperature = NAN;
//     float humidity = NAN;
//     char timeStr[10] = "--:--";
//     char dateStr[12] = "----/--/--";
//     char tomorrowWeather[20] = "N/A";
//     int8_t eyeOffset = 0;
//     int8_t moveDir = 1;
//     unsigned long lastWeatherUpdate = 0;
//     unsigned long lastWiFiCheck = 0;
//     int wifiConnectAttempts = 0;
// } displayData;
// // 动画帧眨眼序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};
// void setup() {
//     Serial.begin(115200);
//     tft.init();
//     tft.setRotation(1);
//     tft.setSwapBytes(true);
//     tft.pushImage(0,0,128,128,p5);
//     WiFi.begin(ssid, password);
//     int wifiRetry = 0;
//     while (WiFi.status() != WL_CONNECTED && wifiRetry < MAX_WIFI_RETRY) {
//       delay(500);
//       tft.setTextDatum(TC_DATUM);
//       tft.drawString("WiFi is loading...", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//       wifiRetry++;
//     }   
//     if(WiFi.status() != WL_CONNECTED) {
//       tft.fillScreen(TFT_BLACK);
//       tft.drawString("WiFi Failed", SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
//       delay(2000);
//       ESP.restart();
//     }
//     Serial.println(WiFi.localIP());
//     configTime(gmtOffset_sec, 0, "pool.ntp.org");
//     client.setServer(mqttServer, mqttPort);
//     client.setCallback([](char* topic, byte* payload, unsigned int length) {
//         StaticJsonDocument<200> doc;
//         deserializeJson(doc, payload, length);
//         displayData.temperature = doc["temperature"] | NAN;
//         displayData.humidity = doc["humidity"] | NAN;
//     });
//     mqttReconnect();
//     // 首次获取天气数据
//     fetchWeather();
//     tft.fillScreen(TFT_BLACK);
// }

// void mqttReconnect() {
//     while (!client.connect("ESP32Client")) delay(1000);
//     client.subscribe(mqttTopic);
// }

// void updateDateTime() {
//     time_t now;
//     struct tm timeinfo;
//     time(&now);
//     localtime_r(&now, &timeinfo);
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }

// void drawDataArea() {
//     // 温度显示（左下角）
//     tft.setTextColor(TFT_CYAN, TFT_BLACK);
//     tft.setTextDatum(BL_DATUM);
//     tft.drawString("TEM:" + String(displayData.temperature, 1) + "C", 5, SCREEN_HEIGHT - 5);

//     // 湿度显示（右下角）
//     tft.setTextColor(TFT_GREEN, TFT_BLACK);
//     tft.setTextDatum(BR_DATUM);
//     tft.drawString("HUM:" + String(displayData.humidity, 1) + "%", SCREEN_WIDTH - 5, SCREEN_HEIGHT - 5);

//     // 时间显示
//     tft.setTextColor(TFT_WHITE, TFT_BLACK);
//     tft.setTextDatum(TC_DATUM);
//     tft.setTextSize(3);
//     tft.drawString(displayData.timeStr, SCREEN_WIDTH / 2, DATA_TOP + 5);

//     // 日期显示，向左移动
//     tft.setTextColor(TFT_YELLOW, TFT_BLACK);
//     tft.setTextSize(1);
//     tft.setTextDatum(TL_DATUM);
//     tft.drawString(displayData.dateStr, 5, DATA_TOP + 35);

//     // 明天天气显示
//     tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
//     tft.setTextSize(1);
//     tft.setTextDatum(TR_DATUM);
//     tft.drawString(displayData.tomorrowWeather, SCREEN_WIDTH - 15, DATA_TOP + 35);
// }

// void drawAnimation() {
//     static unsigned long lastBlink = 0;
//     static uint8_t animPhase = 0;
//     // 清空动画区域
//     tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);
//     // 眼睛移动控制（20ms更新）
//     if (millis() - lastBlink > 20) {
//         displayData.eyeOffset += displayData.moveDir;
//         if (abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//         lastBlink = millis();
//     }
//     // 加速眨眼状态机
//     static unsigned long blinkTimer = 0;
//     static uint8_t blinkState = 0;
//     if (millis() - blinkTimer > BLINK_CYCLE / 4) { // 每100ms切换一帧
//         blinkState = (blinkState + 1) % 4;
//         blinkTimer = millis();
//     }
//     // 计算眼睛位置
//     int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
//     int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;

//     // 绘制动态眼睛
//     tft.pushImage(leftX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);

//     tft.pushImage(rightX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);
//     delay(2000);
// }

// // 获取天气数据
// void fetchWeather() {
//     if (WiFi.status()!= WL_CONNECTED) return;
//     HTTPClient http;
//     const int httpPort = 80;
//     if (!espClient.connect(host, httpPort)) {
//         Serial.println("connection failed");
//         return;
//     }
//     String url = "/v3/weather/daily.json?key=" + String(Privat_Key) + "&location=" + String(City) + "&language=en&unit=c&start=0&days=2";
//     espClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
//                     "Host: " + String(host) + "\r\n" +
//                     "Connection: close\r\n\r\n");
//     delay(1000);
//     String answer;
//     while (espClient.available()) {
//         String line = espClient.readStringUntil('\r');
//         answer += line;
//     }
//     espClient.stop();
//     // 提取JSON数据
//     String jsonAnswer;
//     int jsonIndex;
//     for (int i = 0; i < answer.length(); i++) {
//         if (answer[i] == '{') {
//             jsonIndex = i;
//             break;
//         }
//     }
//     jsonAnswer = answer.substring(jsonIndex);
//     Serial.println("Xingtai Weather JSON data:");
//     Serial.println(jsonAnswer);
//     const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
//     DynamicJsonDocument doc(capacity);
//     deserializeJson(doc, jsonAnswer);
//     JsonObject results_0 = doc["results"][0];
//     JsonArray daily = results_0["daily"];
//     if (daily.size() > 1) {
//         JsonObject tomorrow = daily[1];
//         const char* weather = tomorrow["text_day"];
//         if (weather!= nullptr) {
//             strncpy(displayData.tomorrowWeather, weather, sizeof(displayData.tomorrowWeather) - 1);
//             displayData.tomorrowWeather[sizeof(displayData.tomorrowWeather) - 1] = '\0';
//         }
//     }
//     displayData.lastWeatherUpdate = millis();
// }

// void loop() {
//     if (!client.connected()) mqttReconnect();
//     client.loop();
//     // 检查 WiFi 连接
//     if (millis() - displayData.lastWiFiCheck > 5000) {
//         if (WiFi.status()!= WL_CONNECTED) {
//             displayData.wifiConnectAttempts++;
//             tft.pushImage(0,0,128,128,p5);
//             if (displayData.wifiConnectAttempts > 30) {
//                 Serial.println("Lost WiFi connection. Restarting...");
//                 ESP.restart();
//             }
//             WiFi.reconnect();
//         } else {
//             displayData.wifiConnectAttempts = 0;
//         }
//         displayData.lastWiFiCheck = millis();
//     }

//     static unsigned long lastDataUpdate = 0;
//     if (millis() - lastDataUpdate >= 1000) {
//         updateDateTime();
//         drawDataArea();
//         lastDataUpdate = millis();
//     }
//     // 每 5 分钟更新一次天气
//     if (millis() - displayData.lastWeatherUpdate >= 5 * 60 * 1000) {
//         fetchWeather();
//         drawDataArea();
//     }
//     // 保持 30FPS 动画刷新
//     static unsigned long lastAnimUpdate = 0;
//     if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//         drawAnimation();
//         lastAnimUpdate = millis();
//     }
// }


//#####################################################################################################################
//#####################################################################################################################
//#####################################################################################################################

//#####################################################################################################################
//#####################################################################################################################
//#####################################################################################################################
//#####################################################################################################################
//#####################################################################################################################

// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include <HTTPClient.h>
// #include "pic.h"

// // 心知天气配置
// extern const char* host = "api.seniverse.com";
// extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     // 输入你的密钥
// extern char* City = "XingTai";  

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* Topicsensor = "sensor";
// const char* Topicled = "led";

// // 定义 6 个按钮引脚
// const int buttonPins[6] = {18, 19, 25, 27, 32, 33};
// // 用于记录每个按钮按下的次数
// int pressCounts[6] = {0};
// // 用于记录每个按钮上一次的状态
// int lastButtonStates[6];
// // 定义一个全局变量来存储背景颜色
// uint16_t yanse = TFT_BLACK;

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 33        // 加快帧率至30FPS
// #define EYE_SPACING 80
// #define MAX_OFFSET 10
// #define BLINK_CYCLE 400       // 眨眼周期缩短至400ms
// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT
// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();
// // 时区配置
// const long gmtOffset_sec = 8 * 3600;
// struct {
//     float temperature = NAN;
//     float humidity = NAN;
//     char timeStr[10] = "--:--";
//     char dateStr[12] = "----/--/--";
//     char tomorrowWeather[20] = "N/A";
//     int8_t eyeOffset = 0;
//     int8_t moveDir = 1;
//     unsigned long lastWeatherUpdate = 0;
//     unsigned long lastWiFiCheck = 0;
//     int wifiConnectAttempts = 0;
// } displayData;
// // 动画帧眨眼序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};

// // 修改MQTT重连函数
// void mqttReconnect() {
//     while (!client.connected()) {
//         Serial.print("尝试连接MQTT服务器...");       
//         // 生成唯一客户端ID
//         String clientId = "ESP32Client-";
//         clientId += String(random(0xffff), HEX);
        
//         if (client.connect(clientId.c_str())) {
//             Serial.println("连接成功!");
            
//             // 订阅主题并检查结果
//             if(client.subscribe(Topicled)){
//                 Serial.println("成功订阅LED主题");
//             } else {
//                 Serial.println("订阅LED主题失败");
//             }
            
//             if(client.subscribe(Topicsensor)){
//                 Serial.println("成功订阅传感器主题");
//             } else {
//                 Serial.println("订阅传感器主题失败");
//             }
            
//         } else {
//             Serial.print("失败，错误代码: ");
//             Serial.print(client.state());
//             Serial.println(" 5秒后重试...");
//             delay(5000);
//         }
//     }
// }

// void setup() {
//     Serial.begin(115200);
//     tft.init();
//     tft.setRotation(1);
//     tft.fillScreen(TFT_BLACK);
//     tft.setSwapBytes(true);
//     // 初始化每个按钮引脚为输入上拉模式
//     for (int i = 0; i < 6; i++) {
//       pinMode(buttonPins[i], INPUT_PULLUP);
//       lastButtonStates[i] = HIGH;
//     }
//     WiFi.begin(ssid, password);
//     while (WiFi.status()!= WL_CONNECTED) {
//         delay(1000);
//         Serial.print(".");
//         displayData.wifiConnectAttempts++;
//         if (displayData.wifiConnectAttempts > 30) {
//             Serial.println("Failed to connect to WiFi. Restarting...");
//             ESP.restart();
//         }
//     }
//     Serial.println("");
//     Serial.println("WiFi connected");
//     Serial.println("IP address: ");
//     Serial.println(WiFi.localIP());
//     configTime(gmtOffset_sec, 0, "pool.ntp.org");
//     client.setServer(mqttServer, mqttPort);
//     client.setCallback(Callback);
//     mqttReconnect();
//     // 首次获取天气数据
//     fetchWeather();
// }

// //时间获取
// void updateDateTime() {
//     time_t now;
//     struct tm timeinfo;
//     time(&now);
//     localtime_r(&now, &timeinfo);
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }
// // 获取天气数据
// void fetchWeather() {
//     if (WiFi.status()!= WL_CONNECTED) return;
//     HTTPClient http;
//     const int httpPort = 80;
//     if (!espClient.connect(host, httpPort)) {
//         Serial.println("connection failed");
//         return;
//     }

//     String url = "/v3/weather/daily.json?key=" + String(Privat_Key) + "&location=" + String(City) + "&language=en&unit=c&start=0&days=2";
//     espClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
//                     "Host: " + String(host) + "\r\n" +
//                     "Connection: close\r\n\r\n");
//     delay(1000);

//     String answer;
//     while (espClient.available()) {
//         String line = espClient.readStringUntil('\r');
//         answer += line;
//     }
//     espClient.stop();
//     // 提取JSON数据
//     String jsonAnswer;
//     int jsonIndex;
//     for (int i = 0; i < answer.length(); i++) {
//         if (answer[i] == '{') {
//             jsonIndex = i;
//             break;
//         }
//     }
//     jsonAnswer = answer.substring(jsonIndex);
//     Serial.println("Xingtai Weather JSON data:");
//     Serial.println(jsonAnswer);
//     const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
//     DynamicJsonDocument doc(capacity);
//     deserializeJson(doc, jsonAnswer);
//     JsonObject results_0 = doc["results"][0];
//     JsonArray daily = results_0["daily"];
//     if (daily.size() > 1) {
//         JsonObject tomorrow = daily[1];
//         const char* weather = tomorrow["text_day"];
//         if (weather!= nullptr) {
//             strncpy(displayData.tomorrowWeather, weather, sizeof(displayData.tomorrowWeather) - 1);
//             displayData.tomorrowWeather[sizeof(displayData.tomorrowWeather) - 1] = '\0';
//         }
//     }
//     displayData.lastWeatherUpdate = millis();
// }

// void drawAnimation() {
//     static unsigned long lastBlink = 0;
//     static uint8_t animPhase = 0;
//     // 清空动画区域
//     tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);
//     // 眼睛移动控制（20ms更新）
//     if (millis() - lastBlink > 20) {
//         displayData.eyeOffset += displayData.moveDir;
//         if (abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//         lastBlink = millis();
//     }
//     // 加速眨眼状态机
//     static unsigned long blinkTimer = 0;
//     static uint8_t blinkState = 0;
//     if (millis() - blinkTimer > BLINK_CYCLE / 4) { // 每100ms切换一帧
//         blinkState = (blinkState + 1) % 4;
//         blinkTimer = millis();
//     }

//     // 计算眼睛位置
//     int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
//     int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;

//     // 绘制动态眼睛
//     tft.pushImage(leftX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);

//     tft.pushImage(rightX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);
//     delay(2000);
// }

// void drawDataArea() {
//     // 温度显示（左下角）
//     tft.setTextColor(TFT_CYAN, yanse);
//     tft.setTextDatum(BL_DATUM);
//     tft.drawString("TEM:" + String(displayData.temperature, 1) + "C", 5, SCREEN_HEIGHT - 5);

//     // 湿度显示（右下角）
//     tft.setTextColor(TFT_GREEN, yanse);
//     tft.setTextDatum(BR_DATUM);
//     tft.drawString("HUM:" + String(displayData.humidity, 1) + "%", SCREEN_WIDTH - 5, SCREEN_HEIGHT - 5);

//     // 时间显示
//     tft.setTextColor(TFT_WHITE, yanse);
//     tft.setTextDatum(TC_DATUM);
//     tft.setTextSize(3);
//     tft.drawString(displayData.timeStr, SCREEN_WIDTH / 2, DATA_TOP + 5);

//     // 日期显示，向左移动
//     tft.setTextColor(TFT_YELLOW, yanse);
//     tft.setTextSize(1);
//     tft.setTextDatum(TL_DATUM);
//     tft.drawString(displayData.dateStr, 5, DATA_TOP + 35);

//     // 明天天气显示
//     tft.setTextColor(TFT_MAGENTA, yanse);
//     tft.setTextSize(1);
//     tft.setTextDatum(TR_DATUM);
//     tft.drawString(displayData.tomorrowWeather, SCREEN_WIDTH - 15, DATA_TOP + 35);
// }

// void Callback(char* topic, byte* payload, unsigned int length) {
//     Serial.print("Message Received [");
//     Serial.print(topic);
//     Serial.print("] ");
//     for (int i = 0; i < length; i++) {
//         Serial.print((char)payload[i]);
//     }
//     Serial.println("");
// //#########################################################
//     String topicStr = String(topic);
//     if (topicStr == "led") {
//         String message = "";
//         for (unsigned int i = 0; i < length; i++) {
//             message += (char)payload[i];
//         }
//         if (message == "0") {
//             // 更新屏幕颜色和背景颜色
//             yanse = TFT_RED;
//             tft.fillScreen(yanse);
//         } else if (message == "00") {
//             // 更新屏幕颜色和背景颜色
//             yanse = TFT_BLACK;
//             tft.fillScreen(yanse);
//         } else if (message == "1") {
//             // 这里可以定义你想要的颜色，例如蓝色
//             yanse = TFT_BLUE;
//             tft.fillScreen(yanse);
//         } else if (message == "11") {
//             // 这里可以定义你想要的颜色，例如果绿色
//             yanse = TFT_GREEN;
//             tft.fillScreen(yanse);
//         }
//     }
// //##################################################################################################################    
//     if (String(topic) == "sensor") {
//         StaticJsonDocument<200> doc;
//         deserializeJson(doc, payload, length);
//         displayData.temperature = doc["temperature"] | NAN;
//         displayData.humidity = doc["humidity"] | NAN;
//     };

// }
  
// void loop() {
//     if (!client.connected()) {
//         Serial.println("MQTT连接断开，尝试重连...");
//         mqttReconnect();
//     }
//     client.loop();  // 确保定期调用loop()
//     // 保持 30FPS 动画刷新
//     static unsigned long lastAnimUpdate = 0;
//     if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//         drawAnimation();
//         lastAnimUpdate = millis();
//     }
// //##############################
//     // 遍历每个按钮引脚
//     for (int i = 0; i < 6; i++) {
//       // 读取当前按钮的状态
//       int currentButtonState = digitalRead(buttonPins[i]);

//       // 检测按钮是否从释放状态变为按下状态
//       if (lastButtonStates[i] == HIGH && currentButtonState == LOW) {
//         // 消抖处理
//         delay(50);
//         // 再次读取按钮状态以确认按下
//         currentButtonState = digitalRead(buttonPins[i]);
//         if (currentButtonState == LOW) {
//           // 按下次数加 1
//           pressCounts[i]++;
//           char message[3];
//           if (pressCounts[i] % 2 == 1) {
//             // 第一次按下（按下次数为奇数）发送如 "0", "1", "2" 等
//             snprintf(message, sizeof(message), "%d", i);
//           } else {
//             // 第二次按下（按下次数为偶数）发送如 "00", "11", "22" 等
//             snprintf(message, sizeof(message), "%d%d", i, i);
//           }
//           // 发布主题消息
//           client.publish(Topicled, message);
//           Serial.print("Sent message: ");
//           Serial.println(message);
//         }
//       }
//       // 更新上一次按钮的状态
//       lastButtonStates[i] = currentButtonState;
//     }
//     // 检查 WiFi 连接
//     if (millis() - displayData.lastWiFiCheck > 5000) {
//         if (WiFi.status()!= WL_CONNECTED) {
//             displayData.wifiConnectAttempts++;
//             if (displayData.wifiConnectAttempts > 30) {
//                 Serial.println("Lost WiFi connection. Restarting...");
//                 ESP.restart();
//             }
//             WiFi.reconnect();
//         } else {
//             displayData.wifiConnectAttempts = 0;
//         }
//         displayData.lastWiFiCheck = millis();
//     }

//     static unsigned long lastDataUpdate = 0;
//     if (millis() - lastDataUpdate >= 1000) {
//         updateDateTime();
//         drawDataArea();
//         lastDataUpdate = millis();
//     }

//     // 每 5 分钟更新一次天气
//     if (millis() - displayData.lastWeatherUpdate >= 5 * 60 * 1000) {
//         fetchWeather();
//         drawDataArea();
//     }
// }





// #include <TFT_eSPI.h>
// #include <SPI.h>
// #include <WiFi.h>
// #include <PubSubClient.h>
// #include <time.h>
// #include <ArduinoJson.h>
// #include <HTTPClient.h>
// #include "pic.h"

// // 心知天气配置
// extern const char* host = "api.seniverse.com";
// extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     // 输入你的密钥
// extern char* City = "XingTai";  

// // 网络配置
// const char* ssid = "1501";
// const char* password = "zyx12345678";

// // MQTT配置
// const char* mqttServer = "broker.emqx.io";
// const int mqttPort = 1883;
// const char* Topicsensor = "sensor";
// const char* Topicled = "led";

// // 定义 6 个按钮引脚
// const int buttonPins[6] = {18, 19, 25, 27, 32, 33};
// // 用于记录每个按钮按下的次数
// int pressCounts[6] = {0};
// // 用于记录每个按钮上一次的状态
// int lastButtonStates[6];
// // 定义一个全局变量来存储背景颜色
// uint16_t yanse = TFT_BLACK;

// // 显示参数
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 128
// #define ANIMATION_HEIGHT 64   // 动画区域高度
// #define ANIMATION_WIDTH 50    // 单侧动画宽度
// #define FRAME_DELAY 33        // 加快帧率至30FPS
// #define EYE_SPACING 80
// #define MAX_OFFSET 10
// #define BLINK_CYCLE 400       // 眨眼周期缩短至400ms
// // 区域划分
// #define ANIM_TOP 0
// #define DATA_TOP ANIMATION_HEIGHT
// WiFiClient espClient;
// PubSubClient client(espClient);
// TFT_eSPI tft = TFT_eSPI();
// // 时区配置
// const long gmtOffset_sec = 8 * 3600;
// struct {
//     float temperature = NAN;
//     float humidity = NAN;
//     char timeStr[10] = "--:--";
//     char dateStr[12] = "----/--/--";
//     char tomorrowWeather[20] = "N/A";
//     int8_t eyeOffset = 0;
//     int8_t moveDir = 1;
//     unsigned long lastWeatherUpdate = 0;
//     unsigned long lastWiFiCheck = 0;
//     int wifiConnectAttempts = 0;
// } displayData;
// // 动画帧眨眼序列
// const uint16_t* animFrames[] = {p1, p2, p3, p4};

// // 修改MQTT重连函数
// void mqttReconnect() {
//     while (!client.connected()) {
//         Serial.print("尝试连接MQTT服务器...");       
//         // 生成唯一客户端ID
//         String clientId = "ESP32Client-";
//         clientId += String(random(0xffff), HEX);
        
//         if (client.connect(clientId.c_str())) {
//             Serial.println("连接成功!");
            
//             // 订阅主题并检查结果
//             if(client.subscribe(Topicled)){
//                 Serial.println("成功订阅LED主题");
//             } else {
//                 Serial.println("订阅LED主题失败");
//             }
            
//             if(client.subscribe(Topicsensor)){
//                 Serial.println("成功订阅传感器主题");
//             } else {
//                 Serial.println("订阅传感器主题失败");
//             }
            
//         } else {
//             Serial.print("失败，错误代码: ");
//             Serial.print(client.state());
//             Serial.println(" 5秒后重试...");
//             delay(5000);
//         }
//     }
// }

// void setup() {
//     Serial.begin(115200);
//     tft.init();
//     tft.setRotation(1);
//     tft.fillScreen(TFT_BLACK);
//     tft.setSwapBytes(true);
//     // 初始化每个按钮引脚为输入上拉模式
//     for (int i = 0; i < 6; i++) {
//       pinMode(buttonPins[i], INPUT_PULLUP);
//       lastButtonStates[i] = HIGH;
//     }
//     WiFi.begin(ssid, password);
//     while (WiFi.status()!= WL_CONNECTED) {
//         delay(1000);
//         Serial.print(".");
//         displayData.wifiConnectAttempts++;
//         if (displayData.wifiConnectAttempts > 30) {
//             Serial.println("Failed to connect to WiFi. Restarting...");
//             ESP.restart();
//         }
//     }
//     Serial.println("");
//     Serial.println("WiFi connected");
//     Serial.println("IP address: ");
//     Serial.println(WiFi.localIP());
//     configTime(gmtOffset_sec, 0, "pool.ntp.org");
//     client.setServer(mqttServer, mqttPort);
//     client.setCallback(Callback);
//     mqttReconnect();
//     // 首次获取天气数据
//     fetchWeather();
// }

// //时间获取
// void updateDateTime() {
//     time_t now;
//     struct tm timeinfo;
//     time(&now);
//     localtime_r(&now, &timeinfo);
//     strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
//     strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
// }
// // 获取天气数据
// void fetchWeather() {
//     if (WiFi.status()!= WL_CONNECTED) return;
//     HTTPClient http;
//     const int httpPort = 80;
//     if (!espClient.connect(host, httpPort)) {
//         Serial.println("connection failed");
//         return;
//     }

//     String url = "/v3/weather/daily.json?key=" + String(Privat_Key) + "&location=" + String(City) + "&language=en&unit=c&start=0&days=2";
//     espClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
//                     "Host: " + String(host) + "\r\n" +
//                     "Connection: close\r\n\r\n");
//     delay(1000);

//     String answer;
//     while (espClient.available()) {
//         String line = espClient.readStringUntil('\r');
//         answer += line;
//     }
//     espClient.stop();
//     // 提取JSON数据
//     String jsonAnswer;
//     int jsonIndex;
//     for (int i = 0; i < answer.length(); i++) {
//         if (answer[i] == '{') {
//             jsonIndex = i;
//             break;
//         }
//     }
//     jsonAnswer = answer.substring(jsonIndex);
//     Serial.println("Xingtai Weather JSON data:");
//     Serial.println(jsonAnswer);
//     const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
//     DynamicJsonDocument doc(capacity);
//     deserializeJson(doc, jsonAnswer);
//     JsonObject results_0 = doc["results"][0];
//     JsonArray daily = results_0["daily"];
//     if (daily.size() > 1) {
//         JsonObject tomorrow = daily[1];
//         const char* weather = tomorrow["text_day"];
//         if (weather!= nullptr) {
//             strncpy(displayData.tomorrowWeather, weather, sizeof(displayData.tomorrowWeather) - 1);
//             displayData.tomorrowWeather[sizeof(displayData.tomorrowWeather) - 1] = '\0';
//         }
//     }
//     displayData.lastWeatherUpdate = millis();
// }

// void drawAnimation() {
//     static unsigned long lastBlink = 0;
//     static uint8_t animPhase = 0;
//     // 清空动画区域
//     tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);
//     // 眼睛移动控制（20ms更新）
//     if (millis() - lastBlink > 20) {
//         displayData.eyeOffset += displayData.moveDir;
//         if (abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
//         lastBlink = millis();
//     }
//     // 加速眨眼状态机
//     static unsigned long blinkTimer = 0;
//     static uint8_t blinkState = 0;
//     if (millis() - blinkTimer > BLINK_CYCLE / 4) { // 每100ms切换一帧
//         blinkState = (blinkState + 1) % 4;
//         blinkTimer = millis();
//     }

//     // 计算眼睛位置
//     int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
//     int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;

//     // 绘制动态眼睛
//     tft.pushImage(leftX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);

//     tft.pushImage(rightX - ANIMATION_WIDTH / 2,
//                   ANIM_TOP + 10,
//                   ANIMATION_WIDTH, ANIMATION_WIDTH,
//                   animFrames[blinkState]);
//     delay(2000);
// }

// void drawDataArea() {
//     // 温度显示（左下角）
//     tft.setTextColor(TFT_CYAN, yanse);
//     tft.setTextDatum(BL_DATUM);
//     tft.drawString("TEM:" + String(displayData.temperature, 1) + "C", 5, SCREEN_HEIGHT - 5);

//     // 湿度显示（右下角）
//     tft.setTextColor(TFT_GREEN, yanse);
//     tft.setTextDatum(BR_DATUM);
//     tft.drawString("HUM:" + String(displayData.humidity, 1) + "%", SCREEN_WIDTH - 5, SCREEN_HEIGHT - 5);

//     // 时间显示
//     tft.setTextColor(TFT_WHITE, yanse);
//     tft.setTextDatum(TC_DATUM);
//     tft.setTextSize(3);
//     tft.drawString(displayData.timeStr, SCREEN_WIDTH / 2, DATA_TOP + 5);

//     // 日期显示，向左移动
//     tft.setTextColor(TFT_YELLOW, yanse);
//     tft.setTextSize(1);
//     tft.setTextDatum(TL_DATUM);
//     tft.drawString(displayData.dateStr, 5, DATA_TOP + 35);

//     // 明天天气显示
//     tft.setTextColor(TFT_WHITE, yanse);
//     tft.setTextSize(1);
//     tft.setTextDatum(TR_DATUM);
//     tft.drawString(displayData.tomorrowWeather, SCREEN_WIDTH - 15, DATA_TOP + 35);
// }

// void Callback(char* topic, byte* payload, unsigned int length) {
//     Serial.print("Message Received [");
//     Serial.print(topic);
//     Serial.print("] ");
//     for (int i = 0; i < length; i++) {
//         Serial.print((char)payload[i]);
//     }
//     Serial.println("");
// //#########################################################
//     String topicStr = String(topic);
//     if (topicStr == "led") {
//         String message = "";
//         for (unsigned int i = 0; i < length; i++) {
//             message += (char)payload[i];
//         }
//         if (message == "0") {
//             // 更新屏幕颜色和背景颜色
//             yanse = TFT_RED;
//             tft.fillScreen(yanse);
//         } else if (message == "00") {
//             // 更新屏幕颜色和背景颜色
//             yanse = TFT_BLACK;
//             tft.fillScreen(yanse);
//         } else if (message == "1") {
//             // 这里可以定义你想要的颜色，例如蓝色
//             yanse = TFT_BLUE;
//             tft.fillScreen(yanse);
//         } else if (message == "11") {
//             // 这里可以定义你想要的颜色，例如果绿色
//             yanse = TFT_GREEN;
//             tft.fillScreen(yanse);
//         }
//     }
// //##################################################################################################################    
//     if (String(topic) == "sensor") {
//         StaticJsonDocument<200> doc;
//         deserializeJson(doc, payload, length);
//         displayData.temperature = doc["temperature"] | NAN;
//         displayData.humidity = doc["humidity"] | NAN;
//     };

// }
  
// void loop() {
//     if (!client.connected()) {
//         Serial.println("MQTT连接断开，尝试重连...");
//         mqttReconnect();
//     }
//     client.loop();  // 确保定期调用loop()
//     // 保持 30FPS 动画刷新
//     static unsigned long lastAnimUpdate = 0;
//     if (millis() - lastAnimUpdate >= FRAME_DELAY) {
//         drawAnimation();
//         lastAnimUpdate = millis();
//     }
// //##############################
//     // 遍历每个按钮引脚
//     for (int i = 0; i < 6; i++) {
//       // 读取当前按钮的状态
//       int currentButtonState = digitalRead(buttonPins[i]);

//       // 检测按钮是否从释放状态变为按下状态
//       if (lastButtonStates[i] == HIGH && currentButtonState == LOW) {
//         // 消抖处理
//         delay(50);
//         // 再次读取按钮状态以确认按下
//         currentButtonState = digitalRead(buttonPins[i]);
//         if (currentButtonState == LOW) {
//           // 按下次数加 1
//           pressCounts[i]++;
//           char message[3];
//           if (pressCounts[i] % 2 == 1) {
//             // 第一次按下（按下次数为奇数）发送如 "0", "1", "2" 等
//             snprintf(message, sizeof(message), "%d", i);
//           } else {
//             // 第二次按下（按下次数为偶数）发送如 "00", "11", "22" 等
//             snprintf(message, sizeof(message), "%d%d", i, i);
//           }
//           // 发布主题消息
//           client.publish(Topicled, message);
//           Serial.print("Sent message: ");
//           Serial.println(message);
//         }
//       }
//       // 更新上一次按钮的状态
//       lastButtonStates[i] = currentButtonState;
//     }
//     // 检查 WiFi 连接
//     if (millis() - displayData.lastWiFiCheck > 5000) {
//         if (WiFi.status()!= WL_CONNECTED) {
//             displayData.wifiConnectAttempts++;
//             if (displayData.wifiConnectAttempts > 30) {
//                 Serial.println("Lost WiFi connection. Restarting...");
//                 ESP.restart();
//             }
//             WiFi.reconnect();
//         } else {
//             displayData.wifiConnectAttempts = 0;
//         }
//         displayData.lastWiFiCheck = millis();
//     }

//     static unsigned long lastDataUpdate = 0;
//     if (millis() - lastDataUpdate >= 1000) {
//         updateDateTime();
//         drawDataArea();
//         lastDataUpdate = millis();
//     }

//     // 每 5 分钟更新一次天气
//     if (millis() - displayData.lastWeatherUpdate >= 5 * 60 * 1000) {
//         fetchWeather();
//         drawDataArea();
//     }
// }




#include <TFT_eSPI.h>
#include <SPI.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <time.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include "pic.h"
// 定义 HTTP 服务器
#include <ESPAsyncWebServer.h>
#include <Preferences.h>
AsyncWebServer server(80);
// 定义 Preferences 对象用于存储配置信息
Preferences preferences;

// 定义热点信息
const char* apSSID = "Zongyuxian";
const char* apPassword = "12345678";
// 心知天气配置
extern const char* host = "api.seniverse.com";
extern const char* Privat_Key = "SSNtAooB8n2aOURwg";     // 输入你的密钥
extern char* City = "XingTai";  


// MQTT配置
const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
const char* Topicsensor = "sensor";
const char* Topicled = "led";
// 定义 GPIO 引脚
const int resetPin = 12;

bool resetFlag = false;
unsigned long resetPressStart = 0;
const unsigned long RESET_HOLD_TIME = 5000;  // 5秒长按

// 定义 6 个按钮引脚
const int buttonPins[6] = {18, 19, 25, 27, 32, 33};
// 用于记录每个按钮按下的次数
int pressCounts[6] = {0};
// 用于记录每个按钮上一次的状态
int lastButtonStates[6];
// 定义一个全局变量来存储背景颜色
uint16_t yanse = TFT_BLACK;

// 显示参数
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 128
#define ANIMATION_HEIGHT 64   // 动画区域高度
#define ANIMATION_WIDTH 50    // 单侧动画宽度
#define FRAME_DELAY 33        // 加快帧率至30FPS
#define EYE_SPACING 80
#define MAX_OFFSET 10
#define BLINK_CYCLE 400       // 眨眼周期缩短至400ms
// 区域划分
#define ANIM_TOP 0
#define DATA_TOP ANIMATION_HEIGHT
WiFiClient espClient;
PubSubClient client(espClient);
TFT_eSPI tft = TFT_eSPI();
// 时区配置
const long gmtOffset_sec = 8 * 3600;
struct {
    float temperature = NAN;
    float humidity = NAN;
    char timeStr[10] = "--:--";
    char dateStr[12] = "----/--/--";
    char tomorrowWeather[20] = "N/A";
    int8_t eyeOffset = 0;
    int8_t moveDir = 1;
    unsigned long lastWeatherUpdate = 0;
    unsigned long lastWiFiCheck = 0;
    int wifiConnectAttempts = 0;
} displayData;
// 动画帧眨眼序列
const uint16_t* animFrames[] = {p1, p2, p3, p4};


// HTML 网页代码（格式化后的）
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
	<head>
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>
			ESP32 WiFi Config
		</title>
		<style>
			/* 动态渐变色背景 */ body { text-align: center; font-family: "Trebuchet MS",
			Arial; background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
			background-size: 400% 400%; animation: gradient 15s ease infinite; height:
			100vh; } @keyframes gradient { 0% { background-position: 0% 50%; } 50%
			{ background-position: 100% 50%; } 100% { background-position: 0% 50%;
			} } /* 美化表单和列表 */ h1, h2 { color: white; } ul { list-style-type: none;
			padding: 0; margin: 0 auto; width: 80%; max-width: 300px; background-color:
			rgba(255, 255, 255, 0.2); border-radius: 10px; box-shadow: 0 0 10px rgba(0,
			0, 0, 0.1); padding: 10px; } li { color: white; padding: 5px; margin: 5px;
			background-color: rgba(255, 255, 255, 0.1); border-radius: 5px; } form
			{ background-color: rgba(255, 255, 255, 0.2); border-radius: 10px; box-shadow:
			0 0 10px rgba(0, 0, 0, 0.1); padding: 20px; width: 80%; max-width: 300px;
			margin: 20px auto; } label { display: block; color: white; margin-bottom:
			5px; } input { margin: 5px; padding: 10px; border: none; border-radius:
			5px; width: 80%; } /* 美化确认按钮 */ input[type="submit"] { background: linear-gradient(to
			right, #007BFF, #00C6FF); color: white; cursor: pointer; transition: all
			0.3s ease; } input[type="submit"]:hover { background: linear-gradient(to
			right, #00C6FF, #007BFF); transform: scale(1.05); }
		</style>
	</head>
	<body>
		<h1>
			ESP32 WiFi Configuration
		</h1>
		<h2>
			Available WiFi Networks:
		</h2>
		<ul id="wifiList">
		</ul>
		<h2>
			Connect to WiFi
		</h2>
		<form action="/connect" method="post">
			<label for="ssid">
				WiFi Name:
			</label>
			<input type="text" id="ssid" name="ssid" required>
			<br>
			<label for="password">
				WiFi Password:
			</label>
			<input type="password" id="password" name="password" required>
			<br>
			<input type="submit" value="Connect">
		</form>
		<script>
			function listNetworks() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/scan', true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var networks = JSON.parse(xhr.responseText);
            var list = document.getElementById('wifiList');
            list.innerHTML = '';
            networks.forEach(function(network) {
                var item = document.createElement('li');
                item.textContent = network;
                list.appendChild(item);
            });
        }
    };
    xhr.send();
}
listNetworks();
		</script>
	</body>

</html>
)rawliteral";

// 处理根路径请求
void handleRoot(AsyncWebServerRequest *request) {
  request->send_P(200, "text/html", index_html);
}

// 处理扫描 WiFi 热点请求
void handleScan(AsyncWebServerRequest *request) {
  int n = WiFi.scanNetworks();
  DynamicJsonDocument doc(1024);
  JsonArray array = doc.to<JsonArray>();
  for (int i = 0; i < n; ++i) {
    array.add(WiFi.SSID(i));
  }
  String json;
  serializeJson(doc, json);
  request->send(200, "application/json", json);
}

// 处理连接 WiFi 请求
void handleConnect(AsyncWebServerRequest *request) {
  if (request->hasParam("ssid", true) && request->hasParam("password", true)) {
    String ssid = request->getParam("ssid", true)->value();
    String password = request->getParam("password", true)->value();

    preferences.begin("wifi_config", false);
    preferences.putString("ssid", ssid);
    preferences.putString("password", password);
    preferences.end();

    WiFi.begin(ssid.c_str(), password.c_str());
    int attempts = 0;
    while (WiFi.status()!= WL_CONNECTED && attempts < 10) {
      delay(1000);
      attempts++;
    }

    if (WiFi.status() == WL_CONNECTED) {
      request->send(200, "text/plain", "Connected to WiFi");
    } else {
      request->send(500, "text/plain", "Failed to connect to WiFi");
    }
  } else {
    request->send(400, "text/plain", "Missing parameters");
  }
}

// 连接到 WiFi
void connectToWiFi() {
  preferences.begin("wifi_config", false);
  String ssid = preferences.getString("ssid", "");
  String password = preferences.getString("password", "");
  preferences.end();
  if (ssid!= "" && password!= "") {
    WiFi.begin(ssid.c_str(), password.c_str());
    int attempts = 0;
    while (WiFi.status()!= WL_CONNECTED && attempts < 10) {
      delay(1000);
      attempts++;
    }
  }
}

// 清除 WiFi 配置信息
void clearWiFiConfig() {
  preferences.begin("wifi_config", false);
  preferences.clear();
  preferences.end();
  // startAPMode();
}

// 开启 AP 模式和 HTTP 服务
// void startAPMode() {
//   WiFi.softAP(apSSID, apPassword);
//   IPAddress IP = WiFi.softAPIP();
//   Serial.print("AP IP address: ");
//   Serial.println(IP);

//   server.on("/", handleRoot);
//   server.on("/scan", handleScan);
//   server.on("/connect", handleConnect);
//   server.begin();
// }
void startAPMode() {
    WiFi.mode(WIFI_AP);
    WiFi.softAP(apSSID, apPassword);
    IPAddress IP = WiFi.softAPIP();
    Serial.print("AP模式已启动，IP地址: ");
    Serial.println(IP);
    server.on("/", handleRoot);
    server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){
        // WiFi扫描逻辑
        int n = WiFi.scanNetworks();
        String json = "[";
        for(int i=0; i<n; i++){
            if(i>0) json += ",";
            json += "\""+WiFi.SSID(i)+"\"";
        }
        json += "]";
        request->send(200, "application/json", json);
    });
    
    server.on("/connect", HTTP_POST, [](AsyncWebServerRequest *request){
        // 连接处理逻辑
        if(request->hasParam("ssid", true) && request->hasParam("password", true)){
            String ssid = request->getParam("ssid", true)->value();
            String password = request->getParam("password", true)->value();           
            preferences.begin("wifi_config", false);
            preferences.putString("ssid", ssid);
            preferences.putString("password", password);
            preferences.end();           
            request->send(200, "text/plain", "配置已保存，正在连接...");
            delay(6000);
            ESP.restart();
        }
        else {
            request->send(400, "text/plain", "参数错误");
        }
    });   
    server.begin();
    Serial.println("HTTP服务器已启动");
}
// 修改MQTT重连函数
void mqttReconnect() {
    while (!client.connected()) {
        Serial.print("尝试连接MQTT服务器...");       
        // 生成唯一客户端ID
        String clientId = "ESP32Client-";
        clientId += String(random(0xffff), HEX);
        
        if (client.connect(clientId.c_str())) {
            Serial.println("连接成功!");            
            // 订阅主题并检查结果
            if(client.subscribe(Topicled)){
                Serial.println("成功订阅LED主题");
            } else {
                Serial.println("订阅LED主题失败");
            }
            
            if(client.subscribe(Topicsensor)){
                Serial.println("成功订阅传感器主题");
            } else {
                Serial.println("订阅传感器主题失败");
            }
            
        } else {
            Serial.print("失败，错误代码: ");
            Serial.print(client.state());
            Serial.println(" 5秒后重试...");
            delay(5000);
        }
    }
}

void setup() {
    Serial.begin(115200);
    tft.init();
    tft.setRotation(1);
    tft.fillScreen(TFT_BLACK);
    tft.setSwapBytes(true);
    // 初始化每个按钮引脚为输入上拉模式
    for (int i = 0; i < 6; i++) {
      pinMode(buttonPins[i], INPUT_PULLUP);
      lastButtonStates[i] = HIGH;
    };
    pinMode(resetPin, INPUT_PULLUP);
    connectToWiFi();
    if (WiFi.status()!= WL_CONNECTED) {
      startAPMode();
    };
    Serial.println(WiFi.localIP());
    configTime(gmtOffset_sec, 0, "pool.ntp.org");
    client.setServer(mqttServer, mqttPort);
    client.setCallback(Callback);
    mqttReconnect();
    // 首次获取天气数据
    fetchWeather();
}

// 新增重置处理函数
void handleResetButton() {
    static bool lastState = HIGH;
    bool currentState = digitalRead(resetPin);
    
    // 状态变化检测
    if(currentState != lastState) {
        delay(50); // 消抖处理
        currentState = digitalRead(resetPin);
    }   
    // 按下检测
    if(currentState == LOW && lastState == HIGH) {
        resetPressStart = millis();
        Serial.println("重置按钮按下");
    }   
    // 长按检测
    if(currentState == LOW && (millis() - resetPressStart > RESET_HOLD_TIME)) {
        Serial.println("检测到长按，清除WiFi配置");
        clearWiFiConfig();
        Serial.println("即将重启进入配网模式...");
        delay(1000);
        ESP.restart();
    }   
    lastState = currentState;
}

//时间获取
void updateDateTime() {
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
    strftime(displayData.timeStr, sizeof(displayData.timeStr), "%H:%M", &timeinfo);
    strftime(displayData.dateStr, sizeof(displayData.dateStr), "%Y/%m/%d", &timeinfo);
}
// 获取天气数据
void fetchWeather() {
    if (WiFi.status()!= WL_CONNECTED) return;
    HTTPClient http;
    const int httpPort = 80;
    if (!espClient.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
    }

    String url = "/v3/weather/daily.json?key=" + String(Privat_Key) + "&location=" + String(City) + "&language=en&unit=c&start=0&days=2";
    espClient.print(String("GET ") + url + " HTTP/1.1\r\n" +
                    "Host: " + String(host) + "\r\n" +
                    "Connection: close\r\n\r\n");
    delay(1000);

    String answer;
    while (espClient.available()) {
        String line = espClient.readStringUntil('\r');
        answer += line;
    }
    espClient.stop();
    // 提取JSON数据
    String jsonAnswer;
    int jsonIndex;
    for (int i = 0; i < answer.length(); i++) {
        if (answer[i] == '{') {
            jsonIndex = i;
            break;
        }
    }
    jsonAnswer = answer.substring(jsonIndex);
    Serial.println("Xingtai Weather JSON data:");
    Serial.println(jsonAnswer);
    const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
    DynamicJsonDocument doc(capacity);
    deserializeJson(doc, jsonAnswer);
    JsonObject results_0 = doc["results"][0];
    JsonArray daily = results_0["daily"];
    if (daily.size() > 1) {
        JsonObject tomorrow = daily[1];
        const char* weather = tomorrow["text_day"];
        if (weather!= nullptr) {
            strncpy(displayData.tomorrowWeather, weather, sizeof(displayData.tomorrowWeather) - 1);
            displayData.tomorrowWeather[sizeof(displayData.tomorrowWeather) - 1] = '\0';
        }
    }
    displayData.lastWeatherUpdate = millis();
}

void drawAnimation() {
    static unsigned long lastBlink = 0;
    static uint8_t animPhase = 0;
    // 清空动画区域
    tft.fillRect(0, ANIM_TOP, SCREEN_WIDTH, ANIMATION_HEIGHT, TFT_BLACK);
    // 眼睛移动控制（20ms更新）
    if (millis() - lastBlink > 20) {
        displayData.eyeOffset += displayData.moveDir;
        if (abs(displayData.eyeOffset) > MAX_OFFSET) displayData.moveDir *= -1;
        lastBlink = millis();
    }
    // 加速眨眼状态机
    static unsigned long blinkTimer = 0;
    static uint8_t blinkState = 0;
    if (millis() - blinkTimer > BLINK_CYCLE / 4) { // 每100ms切换一帧
        blinkState = (blinkState + 1) % 4;
        blinkTimer = millis();
    }

    // 计算眼睛位置
    int leftX = (SCREEN_WIDTH - EYE_SPACING) / 2 + displayData.eyeOffset;
    int rightX = (SCREEN_WIDTH + EYE_SPACING) / 2 + displayData.eyeOffset;

    // 绘制动态眼睛
    tft.pushImage(leftX - ANIMATION_WIDTH / 2,
                  ANIM_TOP + 10,
                  ANIMATION_WIDTH, ANIMATION_WIDTH,
                  animFrames[blinkState]);

    tft.pushImage(rightX - ANIMATION_WIDTH / 2,
                  ANIM_TOP + 10,
                  ANIMATION_WIDTH, ANIMATION_WIDTH,
                  animFrames[blinkState]);
    delay(2000);
}

void drawDataArea() {
    // 温度显示（左下角）
    tft.setTextColor(TFT_CYAN, yanse);
    tft.setTextDatum(BL_DATUM);
    tft.drawString("TEM:" + String(displayData.temperature, 1) + "C", 5, SCREEN_HEIGHT - 5);

    // 湿度显示（右下角）
    tft.setTextColor(TFT_GREEN, yanse);
    tft.setTextDatum(BR_DATUM);
    tft.drawString("HUM:" + String(displayData.humidity, 1) + "%", SCREEN_WIDTH - 5, SCREEN_HEIGHT - 5);

    // 时间显示
    tft.setTextColor(TFT_WHITE, yanse);
    tft.setTextDatum(TC_DATUM);
    tft.setTextSize(3);
    tft.drawString(displayData.timeStr, SCREEN_WIDTH / 2, DATA_TOP + 5);

    // 日期显示，向左移动
    tft.setTextColor(TFT_YELLOW, yanse);
    tft.setTextSize(1);
    tft.setTextDatum(TL_DATUM);
    tft.drawString(displayData.dateStr, 5, DATA_TOP + 35);

    // 明天天气显示
    tft.setTextColor(TFT_WHITE, yanse);
    tft.setTextSize(1);
    tft.setTextDatum(TR_DATUM);
    tft.drawString(displayData.tomorrowWeather, SCREEN_WIDTH - 15, DATA_TOP + 35);
}

void Callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("Message Received [");
    Serial.print(topic);
    Serial.print("] ");
    for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
    }
    Serial.println("");
//#########################################################
    String topicStr = String(topic);
    if (topicStr == "led") {
        String message = "";
        for (unsigned int i = 0; i < length; i++) {
            message += (char)payload[i];
        }
        if (message == "0") {
            // 更新屏幕颜色和背景颜色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "00") {
            // 更新屏幕颜色和背景颜色
            yanse = TFT_RED;
            tft.fillScreen(yanse);
        } else if (message == "1") {
            // 这里可以定义你想要的颜色，例如蓝色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "11") {
            // 这里可以定义你想要的颜色，例如果绿色
            yanse = TFT_CYAN;
            tft.fillScreen(yanse);
        } else if (message == "2") {
            // 更新屏幕颜色和背景颜色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "22") {
            // 这里可以定义你想要的颜色，例如蓝色
            yanse = TFT_YELLOW;
            tft.fillScreen(yanse);
        } else if (message == "3") {
            // 这里可以定义你想要的颜色，例如果绿色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "33") {
            // 更新屏幕颜色和背景颜色
            yanse = TFT_GREEN;
            tft.fillScreen(yanse);
        } else if (message == "4") {
            // 这里可以定义你想要的颜色，例如蓝色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "44") {
            // 这里可以定义你想要的颜色，例如果绿色
            yanse = TFT_BLUE;
            tft.fillScreen(yanse);
        } else if (message == "5") {
            // 更新屏幕颜色和背景颜色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "55") {
            // 这里可以定义你想要的颜色，例如蓝色
            yanse = TFT_PURPLE;
            tft.fillScreen(yanse);
        } else if (message == "6") {
            // 这里可以定义你想要的颜色，例如果绿色
            yanse = TFT_BLACK;
            tft.fillScreen(yanse);
        } else if (message == "66") {
            // 这里可以定义你想要的颜色，例如果绿色
            yanse = TFT_MAROON;
            tft.fillScreen(yanse);
        }
    }
//##################################################################################################################    
    if (String(topic) == "sensor") {
        StaticJsonDocument<200> doc;
        deserializeJson(doc, payload, length);
        displayData.temperature = doc["temperature"] | NAN;
        displayData.humidity = doc["humidity"] | NAN;
    };

}

void loop() {
    if (!client.connected()) {
        Serial.println("MQTT连接断开，尝试重连...");
        mqttReconnect();
    }
    client.loop();  // 确保定期调用loop()
    handleResetButton();
    // 保持 30FPS 动画刷新
    static unsigned long lastAnimUpdate = 0;
    if (millis() - lastAnimUpdate >= FRAME_DELAY) {
        drawAnimation();
        lastAnimUpdate = millis();
    }
//##############################
    // 遍历每个按钮引脚
    for (int i = 0; i < 6; i++) {
      // 读取当前按钮的状态
      int currentButtonState = digitalRead(buttonPins[i]);

      // 检测按钮是否从释放状态变为按下状态
      if (lastButtonStates[i] == HIGH && currentButtonState == LOW) {
        // 消抖处理
        delay(50);
        // 再次读取按钮状态以确认按下
        currentButtonState = digitalRead(buttonPins[i]);
        if (currentButtonState == LOW) {
          // 按下次数加 1
          pressCounts[i]++;
          char message[3];
          if (pressCounts[i] % 2 == 1) {
            // 第一次按下（按下次数为奇数）发送如 "0", "1", "2" 等
            snprintf(message, sizeof(message), "%d", i);
          } else {
            // 第二次按下（按下次数为偶数）发送如 "00", "11", "22" 等
            snprintf(message, sizeof(message), "%d%d", i, i);
          }
          // 发布主题消息
          client.publish(Topicled, message);
          Serial.print("Sent message: ");
          Serial.println(message);
        }
      }
      // 更新上一次按钮的状态
      lastButtonStates[i] = currentButtonState;
    }

    static unsigned long lastDataUpdate = 0;
    if (millis() - lastDataUpdate >= 1000) {
        updateDateTime();
        drawDataArea();
        lastDataUpdate = millis();
    }

    // 每 5 分钟更新一次天气
    if (millis() - displayData.lastWeatherUpdate >= 5 * 60 * 1000) {
        fetchWeather();
        drawDataArea();
    }
}